#include <windows.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include "..\Comun\Transferencia.c"
#include "..\Comun\Parser.c"
#define RES_ERROR_PORT_TYPE -2
#define RES_ERROR_COMMAND_LINE -3
#define RES_OK 0
#define RES_ERROR -1
#define RES_ERROR_PORT_RANGE -4


HANDLE serverDataReceiverThread;
HANDLE serverDataSenderThread;

LPDWORD  receiverThreadName;
LPDWORD senderThreadName;

void WINAPI DataReceiverThread (LPVOID lpParameter);
void WINAPI DataSenderThread(LPVOID lpParameter);
int parseCommandLine(int argc, char* argv[], int *port, char* ip[]);
int cerrarConexion=0;


void main (int argc,char* argv[]){
	
	int port;
	char ip[16];
	int error = 0;

	WSADATA wsaData; //es necesario para la compilacion de sockets en V6.0
	CONEXION conexion;

	if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0) { // es necesario para la inicializacon de la dll WINSOCK32 
	exit(1);
	}

	if(parseCommandLine(argc,argv,&port,&ip)!=RES_OK)
		return RES_ERROR;

	error = trConectar(ip,port,&conexion);

	if (error == 0)	{
		
		  serverDataReceiverThread = CreateThread( 
            NULL,                   // default security attributes
            0,                      // use default stack size  
            DataReceiverThread,       // thread function name
            (LPVOID)&conexion,          // argument to thread function 
            0,                      // use default creation flags 
            &receiverThreadName);   // returns the thread identifier */

		  serverDataSenderThread = CreateThread( 
            NULL,                   // default security attributes
            0,                      // use default stack size  
            DataSenderThread,       // thread function name
            (LPVOID)&conexion,          // argument to thread function 
            0,                      // use default creation flags 
            &senderThreadName);   // returns the thread identifier 

		  WaitForSingleObject(serverDataReceiverThread, INFINITE);
		  //WaitForSingleObject(serverDataSenderThread, INFINITE);
		  //CloseHandle(serverDataReceiverThread);
		  //CloseHandle(serverDataSenderThread);
		  		  
	}
	else{
		//printf("No se ha podido establecer la conexion con el servidor");
	}
}


void WINAPI DataReceiverThread (LPVOID lpParameter){

	char datos[500];
	int cantItems;
	int type = -2;

	CONEXION *pConexion = (CONEXION*)lpParameter;
	
	int message = DataReceiver(pConexion, &datos,  &cantItems, &type);

	switch (message)
	{
		case RES_QUIT: 
		{
			printf("Se ha terminado el programa del lado del servidor. Presione enter para terminar el programa.\n");	
			_endthread();
			break;
		}

		case RES_ERROR_CLOSE_CONNECT: 
		{
			printf("El servidor ha intentado cerrar la conexion pero la operacion no pudo realizarse correctamente.\n");
			break;
		}

		case RES_QUIT_CLIENT: 
		{
			printf("Se ha cerrado la conexion.\n");
			break;
		}
		
		
	}	
}


void WINAPI DataSenderThread (LPVOID lpParameter){

	CONEXION *pConexion = (CONEXION*)lpParameter;
		if (DataSender(pConexion) == RES_QUIT){	
			Sleep(SLEEPTIME);
			trCerrarConexion(pConexion);
	}
	//printf("La conexion ha sido cerrada.\n");
}


/********************************************************************************************** 
 * Parsea el string de entrada en el cual debe recbir un puerto ej: servidor.exe 5900         *
 * devuelve RES_OK si la cantidad de parametros es valida e ingreso un puerto valido          *
 * devuelve RES_ERROR_COMMAND_LINE si hay algun error al recibir o transformar los parametros *
 * *******************************************************************************************/

int parseCommandLine(int argc, char* argv[], int *port, char* ip[]){
	if(argc!=3){
		printf("Error al ingresar los parametros de entrada");
		return RES_ERROR_COMMAND_LINE;
	}
	else{
		int size;
		int i;
		size=strlen(argv[2]);
		for(i=0;i<size;i++){
			if ((argv[2][i]<'0') || (argv[2][i]>'9')){
				printf("Error al ingresar un puerto de tipo erroneo");	
				return RES_ERROR_PORT_TYPE;
			}
		}
		(*port)=atoi(argv[2]);
		if (((*port) <=1023) || ((*port)>65535)){ /* Si esta fuera de rango.. */
			printf("Error al ingresar un puerto fuera del rango");
			return RES_ERROR_PORT_RANGE; 
		}
		//TODO::validar ip 
		strcpy(ip,argv[1]);
		ip[strlen(argv[1])]='\0';
		return RES_OK;
	}
}


